<template>
    <el-dialog title="上传文件" v-model="model" width="30%" :before-close="handleClose" center>
        <el-form ref="inst_rule_form" :rules="rules" :model="form_data" label-width="auto" status-icon
            style="max-width: 600px">
            <el-form-item label="Song Title" prop="title">
                <el-input v-model="form_data.title" placeholder="song title" />
            </el-form-item>
            <el-form-item label="Artist" prop="artist">
                <el-input v-model="form_data.artist" placeholder="artist" />
            </el-form-item>
            <el-form-item label="Lyricist" prop="lyricist">
                <el-input v-model="form_data.lyricist" placeholder="lyricist" />
            </el-form-item>
            <el-form-item label="Composer" prop="composer">
                <el-input v-model="form_data.composer" placeholder="composer" />
            </el-form-item>
            <el-form-item label="Release Date" prop="release_date">
                <!-- <el-input v-model="form.year" placeholder="year" /> -->
                <el-date-picker v-model="form_data.release_date" type="date" aria-label="Pick a date"
                    placeholder="Pick a date" />
            </el-form-item>
            <el-form-item label="Genre" prop="genre">
                <el-select-v2 v-model="form_data.genre" placeholder="genre" :options="GENRE_OPTIONS" />
            </el-form-item>
            <el-form-item label="Album" prop="album">
                <el-input v-model="form_data.album" placeholder="album" />
            </el-form-item>
            <el-form-item label="Lyric" prop="lyrics">
                <el-input v-model="form_data.lyrics" placeholder="lyric" type="textarea" />
            </el-form-item>
            <el-form-item label="From Url">
                <el-switch v-model="from_url" />
            </el-form-item>
            <el-form-item v-if="!from_url" label="File" prop="file_path">
                <el-upload class="upload-file" ref="inst_upload" drag action="#" :http-request="customUpload"
                    :accept="accpetTypes" method="put" :on-change="handleChange" :on-error="handleError"
                    :on-success="handleSuccess" :auto-upload="false" :limit="1" :show-file-list="true"
                    :before-upload="beforeUpload" :on-exceed="handleExceed">
                    <el-icon class="el-icon--upload"><upload-filled /></el-icon>
                    <div class="el-upload__text">
                        Drop file here or <em>click to upload</em>
                    </div>
                    <template #tip>
                        <div class="el-upload__tip">
                            audio/* files with a size less than 15Mb
                        </div>
                    </template>
                </el-upload>
            </el-form-item>
            <el-form-item v-if="from_url" label="Url" prop="file_path">
                <el-input v-model="source_url" placeholder="source url" />
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="handleSubmit" :loading="loading">Create</el-button>
                <el-button @click="handleCancel">Cancel</el-button>
            </el-form-item>
        </el-form>
    </el-dialog>
</template>

<script lang="ts" setup>

// import {GENRE_OPTIONS} from '../composables/Upload'
// import type {SongMeta} from '../composables/Upload'
import { GENRE_OPTIONS } from '@/enums/GenreEnum'
import SongsAPI, { SongMeta } from '@/api/songs'
import { minio_upload } from '@/utils/minio_req'

import { reactive, nextTick } from 'vue'
import { UploadFilled } from '@element-plus/icons-vue'
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
// import axios from 'axios'
import type { UploadInstance, UploadProgressEvent, UploadRawFile, UploadRequestOptions, UploadFile, UploadFiles, UploadUserFile, FormInstance, FormRules } from 'element-plus'
// import type {AxiosRequestConfig, AxiosProgressEvent} from 'axios'
// import SongsAPI from '@/api/songs'

const model = defineModel<boolean>()

const upload_url = ref('') // 上传文件的url

const accpetTypes = ref('.mp3,.wav,.ogg,.m4a,.aac,audio/*')

const validTypes = ['mp3', 'wav', 'ogg', 'm4a', 'aac']

// 所上传的文件来自本地或者其他url，默认为本地
const from_url = ref(false)
const source_url = ref('')

const loading = ref(false)

// 记录upload组件的文件列表，用于提交前检验是否有文件
let file_list: UploadFiles = []

const form_data = reactive<SongMeta>({
    title: '',
    artist: '',
    composer: '',
    lyricist: '',
    release_date: '2099-02-04',
    genre: GENRE_OPTIONS[0].value,
    album: '',
    lyrics: '',
    file_path: '',
    song_id: 0,      // useless, 为了符合后端接口要求
    created_at: '1970-01-01T00:00:00', // useless
    updated_at: '1970-01-01T00:00:00'  // useless
})

const inst_upload = ref<UploadInstance>()
const inst_rule_form = ref<FormInstance>()


function resetForm() {
    inst_rule_form.value!.resetFields()
    inst_upload.value?.clearFiles()
    source_url.value = ''

}

function handleClose(done: () => void) {
    console.log('close')
    resetForm()
    done()
}

async function handleSubmit() {
    // 检查歌曲是否已经存在
    let cancel = await check_song_title()
    if (cancel) {
        return
    }

    await nextTick();
    await inst_rule_form.value!.validate((valid, fields) => {
        if (valid) {
            console.log('submit!')
            if (from_url.value) {
                upload_by_url().then(() => {
                })
            }
            else {
                inst_upload.value?.submit()
            }
        } else {
            console.log('error submit!', fields)
        }
    })

}

async function upload_by_url() {
    SongsAPI.upload_by_url(form_data, source_url.value)
        .then((response) => {
            console.log(response)
            ElMessage.success('Upload success!')
            resetForm()
        }).catch((error) => {
            console.log(error)
            ElMessage.error('Upload failed!')
        })
}

function handleCancel() {
    console.log('cancel!')
    model.value = false
    resetForm()
}

function handleSuccess(_response: any, _file: UploadFile, _fileList: UploadFiles) {
    ElMessage.success('Upload success!')
    resetForm()
}

function handleError(err: Error, _file: UploadFile, _fileList: UploadFiles) {
    console.log('error:', err)
    ElMessage.error('Upload failed!')
}


function handleChange(file: UploadFile, fileList: UploadFiles) {
    console.log('file changed:', file, fileList)
    file_list = fileList
    form_data.title = fileList[0]?.name.split('.')[0]
}

//
function handleExceed(files: File[], uploadFiles: UploadUserFile[]) {
    ElMessage.warning(
        `The limit is 1, you selected ${files.length} files this time, add up to ${files.length + uploadFiles.length
        } totally`
    )
}


const rules = reactive<FormRules<SongMeta>>(
    {
        title: [
            { required: true, message: 'Please input title', trigger: 'blur' },
        ],
        lyricist: [
            { required: false, }
        ],
        composer: [
            { required: false, }
        ],
        artist: [
            { required: true, message: 'Please input artist', trigger: 'blur' },
        ],
        release_date: [
            { required: true, message: 'Please select date', trigger: 'blur' },
        ],
        genre: [
            { required: false, }
        ],
        album: [
            { required: false, }
        ],
        lyrics: [
            { required: false, }
        ],
        file_path: [
            {
                required: true, validator: (_rule: any, _value: any, callback: any) => {
                    if (from_url.value) {
                        if (source_url.value == '') {
                            callback(new Error('Please input url'))
                        }
                        else {
                            let url = new URL(source_url.value)
                            let subfix = url.pathname.split('.').pop()
                            if (!subfix || !validTypes.includes(subfix)) {
                                callback(new Error('Invalid url, no subfix found'))
                            }
                            else {
                                callback()
                            }
                        }
                    }
                    else {
                        do {
                            if (file_list.length == 0) {
                                callback(new Error('Please upload file'))
                                break
                            }
                            let file = file_list[0].raw
                            console.log(file)
                            console.log(file!.name.split('.').pop()!)
                            if (file && !validTypes.includes(file!.name.split('.').pop()!)) {
                                callback(new Error('Invalid file type'))
                                break
                            }

                            callback()
                        } while (false)
                    }
                },
                trigger: 'change'
            }
        ],
    }
)

async function check_song_title() {
    let title = form_data.title.trim()
    console.log('check song title:', title)
    let res = await SongsAPI.get_songs_by_title(title)
    console.log('get songs by title:', res)
    let cancel = false
    if (res.songs.length > 0) {
        let songs = res.songs.map((song) => {
            return `${song.title}(${song.artist})`
        }).join(', ')
        await ElMessageBox.confirm(`already exist ${songs} Continue?`,
            'Warning',
            {
                confirmButtonText: 'conntinue',
                cancelButtonText: 'Cancel',
                type: 'warning',
            }).then(() => {
                console.log('conntinue')
                cancel = false
            })
            .catch(() => {
                cancel = true
            })
    }
    console.log('cancel:', cancel)
    return cancel
}

async function beforeUpload(rawFile: UploadRawFile) {
    console.log('before upload:', rawFile)

    const validTypes = ['audio/mpeg', 'audio/wav', 'audio/flac', 'audio/ogg', 'audio/ogg', 'audio/x-m4a'];  // 音乐文件类型
    const isValidType = validTypes.includes(rawFile.type);

    if (!isValidType) {
        ElMessage.error('Invalid file type, only mp3, wav, flac, ogg files are allowed!');
        return false;
    }
    console.log(rawFile)
    if (rawFile.size / 1024 / 1024 > 15) {
        ElMessage.error('File size can not exceed 15MB!')
        return false
    }
    console.log('get upload url')

    return new Promise(async (resolve, reject) => {
        try {
            const res = await SongsAPI.get_upload_url(form_data.title, rawFile.name.split('.').pop()!)

            upload_url.value = res.url
            form_data.file_path = res.file_path

            await SongsAPI.insert_meta_info(form_data)
            resolve(true)
        }
        catch (err: any) {
            console.log('err:', err)
            // let e = err as AxiosError
            ElMessage.error('Error: ' + err.response?.data?.error)
            reject(false)
        }
    })
}

// 需要以二进制上传不是formData，所以需要自定义上传方法
function customUpload(options: UploadRequestOptions) {
    console.log('custom upload:', options)
    minio_upload(upload_url.value, options.file, options.onProgress)
        .then((res) => {
            options.onSuccess(res);
            console.log('upload success:')
        })
        .catch((err) => {
            console.error('Error uploading file:', err);
            options.onError(err);
        })
}



</script>

<style lang="scss" scoped></style>